home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / Managed / Direct3D / Text3D / Text3D.cs next >
Encoding:
Text File  |  2004-09-27  |  26.6 KB  |  560 lines

  1. //-----------------------------------------------------------------------------
  2. // File: Text3D.cs
  3. //
  4. // Desc: Example code showing how to do text in a Direct3D scene.
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8.  
  9. // #define DEBUG_VS   // Uncomment this line to debug vertex shaders 
  10. // #define DEBUG_PS   // Uncomment this line to debug pixel shaders 
  11.  
  12. using System;
  13. using Microsoft.DirectX;
  14. using Microsoft.DirectX.Direct3D;
  15. using Microsoft.Samples.DirectX.UtilityToolkit;
  16.  
  17. namespace Text3DSample
  18. {
  19.     /// <summary>
  20.     /// Class for rendering text in a 3d scene
  21.     /// </summary>
  22.     public class Text3D : IFrameworkCallback, IDeviceCreation
  23.     {
  24.         #region Creation
  25.         /// <summary>Create a new instance of the class</summary>
  26.         public Text3D(Framework f) 
  27.         { 
  28.             // Store framework
  29.             sampleFramework = f; 
  30.             // Create dialogs
  31.             hud = new Dialog(sampleFramework); 
  32.             sampleUi = new Dialog(sampleFramework); 
  33.         }
  34.         #endregion
  35.  
  36.         // Variables
  37.         private Framework sampleFramework = null; // Framework for samples
  38.         private Sprite textSprite = null; // Sprite for batching text calls
  39.         private FirstPersonCamera camera = new FirstPersonCamera(); // A first person viewing camera
  40.         private Dialog hud = null; // dialog for standard controls
  41.         private Dialog sampleUi = null; // dialog for sample specific controls
  42.  
  43.         // Interop to call get device caps
  44.         private const int LogPixelsY = 90;
  45.         [System.Runtime.InteropServices.DllImport("gdi32.dll")]
  46.         private static extern int GetDeviceCaps(IntPtr hdc, int cap);
  47.  
  48.         // Font scene variables
  49.         private Mesh mesh3DText = null;  // Mesh to draw 3d text
  50.         private Font firstFont = null;
  51.         private Font secondFont = null;
  52.         private Font statsFont = null;
  53.         private Sprite batchSprite = null;
  54.         private Material textMaterial;
  55.  
  56.         private Matrix objectOne = Matrix.Identity;
  57.         private Matrix objectTwo = Matrix.Identity;
  58.  
  59.         private string fontName = "Arial";
  60.         private const int FontSize = 15;
  61.         private const int FontSize2 = 12;
  62.  
  63.         private System.Drawing.Font currentFont;
  64.  
  65.         private const string BigText = "This is a single call to Font.DrawText() with a large text buffer.  It shows that Font supports word wrapping. " +
  66.             "If you resize the window, the words will automatically wrap to the next line.  It also supports\r\nhard line breaks.  Font also supports " +
  67.             "Unicode text with correct word wrapping for right-to-left languages.";
  68.  
  69.         /// <summary>
  70.         /// Called during device initialization, this code checks the device for some 
  71.         /// minimum set of capabilities, and rejects those that don't pass by returning false.
  72.         /// </summary>
  73.         public bool IsDeviceAcceptable(Caps caps, Format adapterFormat, Format backBufferFormat, bool windowed)
  74.         {
  75.             // Skip back buffer formats that don't support alpha blending
  76.             if (!Manager.CheckDeviceFormat(caps.AdapterOrdinal, caps.DeviceType, adapterFormat, 
  77.                 Usage.QueryPostPixelShaderBlending, ResourceType.Textures, backBufferFormat))
  78.                 return false;
  79.  
  80.             return true;
  81.         }
  82.  
  83.         /// <summary>
  84.         /// This callback function is called immediately before a device is created to allow the 
  85.         /// application to modify the device settings. The supplied settings parameter 
  86.         /// contains the settings that the framework has selected for the new device, and the 
  87.         /// application can make any desired changes directly to this structure.  Note however that 
  88.         /// the sample framework will not correct invalid device settings so care must be taken 
  89.         /// to return valid device settings, otherwise creating the Device will fail.  
  90.         /// </summary>
  91.         public void ModifyDeviceSettings(DeviceSettings settings, Caps caps)
  92.         {
  93.             // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  94.             // then switch to SWVP.
  95.             if ( (!caps.DeviceCaps.SupportsHardwareTransformAndLight) ||
  96.                 (caps.VertexShaderVersion < new Version(1,1)) )
  97.             {
  98.                 settings.BehaviorFlags = CreateFlags.SoftwareVertexProcessing;
  99.             }
  100.             else
  101.             {
  102.                 settings.BehaviorFlags = CreateFlags.HardwareVertexProcessing;
  103.             }
  104.  
  105.             // This application is designed to work on a pure device by not using 
  106.             // any get methods, so create a pure device if supported and using HWVP.
  107.             if ( (caps.DeviceCaps.SupportsPureDevice) && 
  108.                 ((settings.BehaviorFlags & CreateFlags.HardwareVertexProcessing) != 0 ) )
  109.                 settings.BehaviorFlags |= CreateFlags.PureDevice;
  110.  
  111.             // Debugging vertex shaders requires either REF or software vertex processing 
  112.             // and debugging pixel shaders requires REF.  
  113. #if(DEBUG_VS)
  114.             if (settings.DeviceType != DeviceType.Reference )
  115.             {
  116.                 settings.BehaviorFlags &= ~CreateFlags.HardwareVertexProcessing;
  117.                 settings.BehaviorFlags |= CreateFlags.SoftwareVertexProcessing;
  118.             }
  119. #endif
  120. #if(DEBUG_PS)
  121.             settings.DeviceType = DeviceType.Reference;
  122. #endif
  123.  
  124.         }
  125.  
  126.         /// <summary>
  127.         /// This event will be fired immediately after the Direct3D device has been 
  128.         /// created, which will happen during application initialization and windowed/full screen 
  129.         /// toggles. This is the best location to create Pool.Managed resources since these 
  130.         /// resources need to be reloaded whenever the device is destroyed. Resources created  
  131.         /// here should be released in the Disposing event. 
  132.         /// </summary>
  133.         private void OnCreateDevice(object sender, DeviceEventArgs e)
  134.         {
  135.             int height;
  136.             int logPixels;
  137.             // Initialize all of the fonts
  138.             using(System.Drawing.Graphics g = System.Drawing.Graphics.FromHwnd(sampleFramework.Window))
  139.             {
  140.                 System.IntPtr dc = g.GetHdc();
  141.                 logPixels = GetDeviceCaps(dc, LogPixelsY);
  142.                 g.ReleaseHdc(dc);
  143.             }
  144.  
  145.             height = -FontSize * logPixels / 72;
  146.  
  147.             firstFont = new Font(e.Device, height, 0, FontWeight.Bold,
  148.                 1, false, CharacterSet.Default, Precision.Default, FontQuality.Default, 
  149.                 PitchAndFamily.DefaultPitch | PitchAndFamily.FamilyDoNotCare, fontName);
  150.  
  151.             height = -FontSize2 * logPixels / 72;
  152.             secondFont = new Font(e.Device, height, 0, FontWeight.Bold,
  153.                 0, false, CharacterSet.Default, Precision.Default, FontQuality.Default, 
  154.                 PitchAndFamily.DefaultPitch | PitchAndFamily.FamilyDoNotCare, fontName);
  155.  
  156.             // Initialize the stats font
  157.             statsFont = ResourceCache.GetGlobalInstance().CreateFont(e.Device, 15, 0, FontWeight.Bold, 1, false, CharacterSet.Default,
  158.                 Precision.Default, FontQuality.Default, PitchAndFamily.FamilyDoNotCare | PitchAndFamily.DefaultPitch
  159.                 , "Arial");
  160.  
  161.             batchSprite = new Sprite(e.Device);
  162.  
  163.             // Store font
  164.             currentFont = new System.Drawing.Font(fontName, FontSize);
  165.         }
  166.         
  167.         /// <summary>
  168.         /// This event will be fired immediately after the Direct3D device has been 
  169.         /// reset, which will happen after a lost device scenario. This is the best location to 
  170.         /// create Pool.Default resources since these resources need to be reloaded whenever 
  171.         /// the device is lost. Resources created here should be released in the OnLostDevice 
  172.         /// event. 
  173.         /// </summary>
  174.         private void OnResetDevice(object sender, DeviceEventArgs e)
  175.         {
  176.             SurfaceDescription desc = e.BackBufferDescription;
  177.             // Create a sprite to help batch calls when drawing many lines of text
  178.             textSprite = new Sprite(e.Device);
  179.  
  180.             // Setup UI locations
  181.             hud.SetLocation(desc.Width-170, 0);
  182.             hud.SetSize(170,170);
  183.             sampleUi.SetLocation(desc.Width - 170, desc.Height - 350);
  184.             sampleUi.SetSize(170,300);
  185.  
  186.             // Restore the fonts / sprite
  187.             firstFont.OnResetDevice();
  188.             secondFont.OnResetDevice();
  189.             batchSprite.OnResetDevice();
  190.  
  191.             // Restore the states
  192.             e.Device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;
  193.             e.Device.TextureState[0].ColorArgument2 = TextureArgument.Diffuse;
  194.             e.Device.TextureState[0].ColorOperation = TextureOperation.Modulate;
  195.             e.Device.SamplerState[0].MinFilter = TextureFilter.Linear;
  196.             e.Device.SamplerState[0].MagFilter = TextureFilter.Linear;
  197.  
  198.             e.Device.RenderState.ZBufferEnable = true;
  199.             e.Device.RenderState.DitherEnable = true;
  200.             e.Device.RenderState.SpecularEnable = true;
  201.             e.Device.RenderState.Lighting = true;
  202.             e.Device.RenderState.AmbientColor = unchecked((int)0x80808080);
  203.  
  204.             // Create a light
  205.             Vector3 lightDirection = new Vector3(10,-10,10);
  206.             e.Device.Lights[0].Type = LightType.Directional;
  207.             e.Device.Lights[0].DiffuseColor = new ColorValue(1.0f,1.0f,1.0f,1.0f);
  208.             e.Device.Lights[0].Direction = Vector3.Normalize(lightDirection);
  209.             e.Device.Lights[0].Enabled = true;
  210.  
  211.             // Set the transform matrices
  212.             Vector3 eyeLocation = new Vector3(0.0f,-5.0f,-10.0f);
  213.             Vector3 lookAtPoint = new Vector3(0.2f, 0.0f,  0.0f);
  214.             e.Device.Transform.World = Matrix.Identity;
  215.  
  216.             camera.SetViewParameters(eyeLocation, lookAtPoint);
  217.             float aspectRatio = (float)desc.Width / (float)desc.Height;
  218.             camera.SetProjectionParameters((float)Math.PI / 4, aspectRatio, 1.0f, 1000.0f);
  219.  
  220.             if (mesh3DText != null)
  221.                 mesh3DText.Dispose();
  222.  
  223.             // Create our 3d text mesh
  224.             mesh3DText = Mesh.TextFromFont(e.Device, currentFont, "This is calling Mesh.TextFromFont", 0.001f, 0.4f);
  225.             // Create the material that will be used for the mesh
  226.             textMaterial = new Material();
  227.             textMaterial.AmbientColor = textMaterial.DiffuseColor = new ColorValue(0,16,180,255);
  228.         }
  229.  
  230.         /// <summary>
  231.         /// This event function will be called fired after the Direct3D device has 
  232.         /// entered a lost state and before Device.Reset() is called. Resources created
  233.         /// in the OnResetDevice callback should be released here, which generally includes all 
  234.         /// Pool.Default resources. See the "Lost Devices" section of the documentation for 
  235.         /// information about lost devices.
  236.         /// </summary>
  237.         private void OnLostDevice(object sender, EventArgs e)
  238.         {
  239.             if (firstFont != null)
  240.                 firstFont.OnLostDevice();
  241.             if (secondFont != null)
  242.                 secondFont.OnLostDevice();
  243.             if (batchSprite != null)
  244.                 batchSprite.OnLostDevice();
  245.  
  246.             if (mesh3DText != null)
  247.             {
  248.                 mesh3DText.Dispose();
  249.                 mesh3DText = null;
  250.             }
  251.             if (textSprite != null)
  252.             {
  253.                 textSprite.Dispose();
  254.                 textSprite = null;
  255.             }
  256.         }
  257.  
  258.         /// <summary>
  259.         /// This event will be fired immediately after the Direct3D device has 
  260.         /// been destroyed, which generally happens as a result of application termination or 
  261.         /// windowed/full screen toggles. Resources created in the OnCreateDevice event 
  262.         /// should be released here, which generally includes all Pool.Managed resources. 
  263.         /// </summary>
  264.         private void OnDestroyDevice(object sender, EventArgs e)
  265.         {
  266.             if (firstFont != null)
  267.             {
  268.                 firstFont.Dispose();
  269.                 firstFont = null;
  270.             }
  271.             if (secondFont != null)
  272.             {
  273.                 secondFont.Dispose();
  274.                 secondFont = null;
  275.             }
  276.             if (batchSprite != null)
  277.             {
  278.                 batchSprite.Dispose();
  279.                 batchSprite = null;
  280.             }
  281.         }
  282.  
  283.         /// <summary>
  284.         /// This callback function will be called once at the beginning of every frame. This is the
  285.         /// best location for your application to handle updates to the scene, but is not 
  286.         /// intended to contain actual rendering calls, which should instead be placed in the 
  287.         /// OnFrameRender callback.  
  288.         /// </summary>
  289.         public void OnFrameMove(Device device, double appTime, float elapsedTime)
  290.         {
  291.             // Setup five rotation matrices (for rotating text strings)
  292.             Vector3 vAxis1 = new Vector3(1.0f,2.0f,0.0f);
  293.             Vector3 vAxis2 = new Vector3(1.0f,0.0f,0.0f);
  294.             objectOne = Matrix.RotationAxis(vAxis1, (float)appTime / 2.0f);
  295.             objectTwo = Matrix.RotationAxis(vAxis2, (float)appTime);
  296.  
  297.             objectTwo *= Matrix.Scaling(0.5f, 0.5f, 0.5f);
  298.  
  299.             // Add some translational values to the matrices
  300.             objectOne.M41 = 1.0f;   objectOne.M42 = 6.0f;   objectOne.M43 = 20.0f; 
  301.             objectTwo.M41 = -4.0f;  objectTwo.M42 = -1.0f;  objectTwo.M43 = 0.0f; 
  302.         }
  303.  
  304.         /// <summary>
  305.         /// This callback function will be called at the end of every frame to perform all the 
  306.         /// rendering calls for the scene, and it will also be called if the window needs to be 
  307.         /// repainted. After this function has returned, the sample framework will call 
  308.         /// Device.Present to display the contents of the next buffer in the swap chain
  309.         /// </summary>
  310.         public void OnFrameRender(Device device, double appTime, float elapsedTime)
  311.         {
  312.             // Get the view & projection matrix from camera.
  313.             // User can't control camera for this simple sample
  314.             device.Transform.View = camera.ViewMatrix;
  315.             device.Transform.Projection = camera.ProjectionMatrix;
  316.             bool beginSceneCalled = false;
  317.  
  318.             // Clear the render target and the zbuffer 
  319.             device.Clear(ClearFlags.ZBuffer | ClearFlags.Target, 0, 1.0f, 0);
  320.             try
  321.             {
  322.                 device.BeginScene();
  323.                 beginSceneCalled = true;
  324.  
  325.                 int height = sampleFramework.PresentParameters.BackBufferHeight;
  326.                 System.Drawing.Rectangle rect;
  327.                 // Demonstration 1
  328.                 // Draw a simple line using DrawText
  329. #if (true)
  330.                 // Pass in DrawTextFormat.NoClip so we don't have to calc the bottom/right of the rect
  331.                 firstFont.DrawText(null, "This is a trivial call to Font.DrawText", new System.Drawing.Rectangle(150,200, 0, 0), 
  332.                     DrawTextFormat.NoClip, System.Drawing.Color.Red);
  333. #else
  334.                 // If you wanted to calc the bottom/rect of the rect make these 2 calls
  335.                 rect = new System.Drawing.Rectangle(150,200, 0, 0);
  336.                 firstFont.DrawText(null, "This is a trivial call to DrawText", ref rect, 
  337.                     DrawTextFormat.CalculateRect, System.Drawing.Color.Red);
  338.                 firstFont.DrawText(null, "This is a trivial call to Font.DrawText", rect, 
  339.                     DrawTextFormat.None, System.Drawing.Color.Red);
  340. #endif
  341.     
  342.                 // Demonstration 2
  343.                 // Allow multiple draw calls to sort by texture changes by Sprite
  344.                 // When drawing 2D text use flags: SpriteFlags.AlphaBlend | SpriteFlags.SortTexture
  345.                 // When drawing 3D text use flags: SpriteFlags.AlphaBlend | SpriteFlags.SortDepthBackToFront
  346.                 
  347.                 batchSprite.Begin(SpriteFlags.AlphaBlend | SpriteFlags.SortTexture);
  348.                 rect = new System.Drawing.Rectangle(10, height - 15 * 6, 0, 0);
  349.                 secondFont.DrawText(batchSprite, "These multiple calls to Font.DrawText() using the same Sprite.", 
  350.                     rect, DrawTextFormat.NoClip, unchecked((int)0xffffffff));
  351.                 rect = new System.Drawing.Rectangle(10, height - 15 * 5, 0, 0);
  352.                 secondFont.DrawText(batchSprite, "Font now caches letters on one or more textures.", 
  353.                     rect, DrawTextFormat.NoClip, unchecked((int)0xffffffff));
  354.                 rect = new System.Drawing.Rectangle(10, height - 15 * 4, 0, 0);
  355.                 secondFont.DrawText(batchSprite, "In order to sort by texture state changes on multiple", 
  356.                     rect, DrawTextFormat.NoClip, unchecked((int)0xffffffff));
  357.                 rect = new System.Drawing.Rectangle(10, height - 15 * 3, 0, 0);
  358.                 secondFont.DrawText(batchSprite, "draw calls to DrawText() pass a Sprite and use", 
  359.                     rect, DrawTextFormat.NoClip, unchecked((int)0xffffffff));
  360.                 rect = new System.Drawing.Rectangle(10, height - 15 * 2, 0, 0);
  361.                 secondFont.DrawText(batchSprite, "flags SpriteFlags.AlphaBlend | SpriteFlags.SortTexture", 
  362.                     rect, DrawTextFormat.NoClip, unchecked((int)0xffffffff));
  363.                 batchSprite.End();
  364.     
  365.                 // Demonstration 3:
  366.                 // Word wrapping and unicode text.  
  367.                 // Note that not all fonts support dynamic font linking. 
  368.                 System.Drawing.Rectangle rc = new System.Drawing.Rectangle(10, 60, 
  369.                     sampleFramework.PresentParameters.BackBufferWidth - 150, 
  370.                     sampleFramework.PresentParameters.BackBufferHeight - 10);
  371.  
  372.                 secondFont.DrawText(null, BigText, rc, 
  373.                     DrawTextFormat.Left | DrawTextFormat.WordBreak | DrawTextFormat.ExpandTabs,
  374.                     System.Drawing.Color.CornflowerBlue);
  375.  
  376.  
  377.                 // Draw D3DXFont mesh in 3D (blue)
  378.                 if (mesh3DText != null)
  379.                 {
  380.                     device.Material = textMaterial;
  381.                     device.Transform.World = objectTwo;
  382.                     mesh3DText.DrawSubset(0);
  383.                 }
  384.  
  385.                 // Show frame rate
  386.                 statsFont.DrawText(null, sampleFramework.FrameStats, new System.Drawing.Rectangle(2,0,0,0),
  387.                     DrawTextFormat.NoClip, unchecked((int)0xffffff00));
  388.                 statsFont.DrawText(null, sampleFramework.DeviceStats, new System.Drawing.Rectangle(2,15,0,0),
  389.                     DrawTextFormat.NoClip, unchecked((int)0xffffff00));
  390.  
  391.                 // Show UI
  392.                 hud.OnRender(elapsedTime);
  393.                 sampleUi.OnRender(elapsedTime);
  394.             }
  395.             finally
  396.             {
  397.                 if (beginSceneCalled)
  398.                     device.EndScene();
  399.             }
  400.         }
  401.  
  402.         /// <summary>
  403.         /// Before handling window messages, the sample framework passes incoming windows 
  404.         /// messages to the application through this callback function. If the application sets 
  405.         /// noFurtherProcessing to true, the sample framework will not process the message
  406.         /// </summary>
  407.         public IntPtr OnMsgProc(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam, ref bool noFurtherProcessing)
  408.         {
  409.             // Give the dialog a chance to handle the message first
  410.             if (!hud.MessageProc(hWnd, msg, wParam, lParam))
  411.             {
  412.                 if (!sampleUi.MessageProc(hWnd, msg, wParam, lParam))
  413.                 {
  414.                     // Pass all remaining windows messages to camera so it can respond to user input
  415.                     camera.HandleMessages(hWnd, msg, wParam, lParam);
  416.                 }
  417.             }
  418.             return IntPtr.Zero;
  419.         }
  420.  
  421.         /// <summary>
  422.         /// Adds the guid stuff to the application
  423.         /// </summary>
  424.         public void InitializeApplication()
  425.         {
  426.             int y = 10;
  427.             // Create the buttons
  428.             Button fullScreen = hud.AddButton(2,"Toggle full screen", 35, y, 125,22);
  429.             Button toggleRef = hud.AddButton(3,"Toggle reference (F3)", 35, y += 24, 125,22);
  430.             Button changeDevice = hud.AddButton(4,"Change Device (F2)", 35, y += 24, 125,22);
  431.             // Hook the button events for when these items are clicked
  432.             fullScreen.Click += new EventHandler(OnFullscreenClicked);
  433.             toggleRef.Click += new EventHandler(OnRefClicked);
  434.             changeDevice.Click += new EventHandler(OnChangeDeviceClicked);
  435.  
  436.             // Now add the sample specific UI
  437.             y = 10;
  438.             Button changeFont = sampleUi.AddButton(5, "Change Font", 35, y += 24, 125, 22);
  439.             changeFont.Click += new EventHandler(OnChangeFont);
  440.             
  441.         }
  442.  
  443.         /// <summary>Called when the change device button is clicked</summary>
  444.         private void OnChangeDeviceClicked(object sender, EventArgs e)
  445.         {
  446.             sampleFramework.ShowSettingsDialog(!sampleFramework.IsD3DSettingsDialogShowing);
  447.         }
  448.  
  449.         /// <summary>Called when the full screen button is clicked</summary>
  450.         private void OnFullscreenClicked(object sender, EventArgs e)
  451.         {
  452.             sampleFramework.ToggleFullscreen();
  453.         }
  454.  
  455.         /// <summary>Called when the ref button is clicked</summary>
  456.         private void OnRefClicked(object sender, EventArgs e)
  457.         {
  458.             sampleFramework.ToggleReference();
  459.         }
  460.  
  461.         /// <summary>Called when the change font button is clicked</summary>
  462.         private void OnChangeFont(object sender, EventArgs e)
  463.         {
  464.             System.Windows.Forms.FontDialog dlg = new System.Windows.Forms.FontDialog();
  465.  
  466.             // Show the dialog
  467.             dlg.FontMustExist = true;
  468.             dlg.Font = currentFont;
  469.  
  470.             // Make the framework go back to windowed if it isn't
  471.             if (!sampleFramework.IsWindowed)
  472.                 sampleFramework.ToggleFullscreen();
  473.  
  474.             if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) // We selected something
  475.             {
  476.                 currentFont = dlg.Font;
  477.                 if (firstFont != null)
  478.                     firstFont.Dispose();
  479.  
  480.                 // Set the new font
  481.                 firstFont = new Font(sampleFramework.Device, currentFont);
  482.  
  483.                 if (mesh3DText != null)
  484.                     mesh3DText.Dispose();
  485.  
  486.                 // Create our 3d text mesh
  487.                 mesh3DText = Mesh.TextFromFont(sampleFramework.Device, currentFont
  488.                     , "This is calling Mesh.TextFromFont", 0.001f, 0.4f);
  489.             }
  490.         }
  491.         /// <summary>
  492.         /// Entry point to the program. Initializes everything and goes into a message processing 
  493.         /// loop. Idle time is used to render the scene.
  494.         /// </summary>
  495.         static int Main() 
  496.         {
  497.             using(Framework sampleFramework = new Framework())
  498.             {
  499.                 Text3D sample = new Text3D(sampleFramework);
  500.                 // Set the callback functions. These functions allow the sample framework to notify
  501.                 // the application about device changes, user input, and windows messages.  The 
  502.                 // callbacks are optional so you need only set callbacks for events you're interested 
  503.                 // in. However, if you don't handle the device reset/lost callbacks then the sample 
  504.                 // framework won't be able to reset your device since the application must first 
  505.                 // release all device resources before resetting.  Likewise, if you don't handle the 
  506.                 // device created/destroyed callbacks then the sample framework won't be able to 
  507.                 // recreate your device resources.
  508.                 sampleFramework.Disposing += new EventHandler(sample.OnDestroyDevice);
  509.                 sampleFramework.DeviceLost += new EventHandler(sample.OnLostDevice);
  510.                 sampleFramework.DeviceCreated += new DeviceEventHandler(sample.OnCreateDevice);
  511.                 sampleFramework.DeviceReset += new DeviceEventHandler(sample.OnResetDevice);
  512.  
  513.                 sampleFramework.SetWndProcCallback(new WndProcCallback(sample.OnMsgProc));
  514.                 sampleFramework.SetCallbackInterface(sample);
  515.  
  516.                 try
  517.                 {
  518.  
  519.                     // Show the cursor and clip it when in full screen
  520.                     sampleFramework.SetCursorSettings(true, true);
  521.  
  522.                     // Initialize
  523.                     sample.InitializeApplication();
  524.  
  525.                     // Initialize the sample framework and create the desired window and Direct3D 
  526.                     // device for the application. Calling each of these functions is optional, but they
  527.                     // allow you to set several options which control the behavior of the sampleFramework.
  528.                     sampleFramework.Initialize( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  529.                     sampleFramework.CreateWindow("Text3D");
  530.                     sampleFramework.CreateDevice( 0, true, Framework.DefaultSizeWidth, Framework.DefaultSizeHeight, 
  531.                         sample);
  532.  
  533.                     // Pass control to the sample framework for handling the message pump and 
  534.                     // dispatching render calls. The sample framework will call your FrameMove 
  535.                     // and FrameRender callback when there is idle time between handling window messages.
  536.                     sampleFramework.MainLoop();
  537.  
  538.                 }
  539. #if(DEBUG)
  540.                 catch (Exception e)
  541.                 {
  542.                     // In debug mode show this error (maybe - depending on settings)
  543.                     sampleFramework.DisplayErrorMessage(e);
  544. #else
  545.             catch
  546.             {
  547.                 // In release mode fail silently
  548. #endif
  549.                     // Ignore any exceptions here, they would have been handled by other areas
  550.                     return (sampleFramework.ExitCode == 0) ? 1 : sampleFramework.ExitCode; // Return an error code here
  551.                 }
  552.  
  553.                 // Perform any application-level cleanup here. Direct3D device resources are released within the
  554.                 // appropriate callback functions and therefore don't require any cleanup code here.
  555.                 return sampleFramework.ExitCode;
  556.             }
  557.         }
  558.     }
  559. }
  560.